package com.example.myapplication;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.example.myapplication.databinding.ActivityMainBinding;

import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration appBarConfiguration;
    private ActivityMainBinding binding;

    // 用于日志输出的标识符
    private static final String TAG = "BLEClient";
    // 权限请求的请求码
    private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1001;
    // 扫描持续时间（10秒）
    private static final long SCAN_PERIOD = 10000;
    // 蓝牙适配器，用于控制蓝牙功能
    private BluetoothAdapter bluetoothAdapter;
    // 蓝牙LE扫描器，负责扫描BLE设备
    private BluetoothLeScanner bluetoothLeScanner;
    // 扫描状态标志
    private boolean isScanning = false;
    // 用于处理扫描结果的Handler，延时任务
    private Handler handler = new Handler(Looper.getMainLooper());

    private TextView deviceInfoTextView;
    private Button scanButton;
    private StringBuilder info;

    // 自定义服务的UUID（根据实际情况修改）
//    private static final UUID CUSTOM_SERVICE_UUID = UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        deviceInfoTextView = findViewById(R.id.device_info);
        scanButton = findViewById(R.id.scan_button);

        // 初始化BluetoothAdapter
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();

        // 检查设备是否支持BLE
        if (bluetoothAdapter == null || !getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "设备不支持BLE", Toast.LENGTH_SHORT).show();
            finish();
        }

        // 设置扫描按钮的点击监听器
        scanButton.setOnClickListener(v -> {
            if (isScanning) {
                // 停止扫描
                stopScan();
            } else {
                info = new StringBuilder();
                // 检查权限并开始扫描
                checkPermissionsAndStartScan();
            }
        });
    }

    // 检查并请求必要的权限
    private void checkPermissionsAndStartScan() {
        List<String> permissionsNeeded = new ArrayList<>();

        // 检查不同Android版本的权限
        // Android 12及以上：需要 BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 权限
        // Android 12以下：需要位置权限和传统蓝牙权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN)
                    != PackageManager.PERMISSION_GRANTED) {
                permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN);
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT)
                    != PackageManager.PERMISSION_GRANTED) {
                permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT);
            }
        } else {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH)
                    != PackageManager.PERMISSION_GRANTED) {
                permissionsNeeded.add(Manifest.permission.BLUETOOTH);
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN)
                    != PackageManager.PERMISSION_GRANTED) {
                permissionsNeeded.add(Manifest.permission.BLUETOOTH_ADMIN);
            }
        }

        if (!permissionsNeeded.isEmpty()) {
            ActivityCompat.requestPermissions(this,
                    permissionsNeeded.toArray(new String[0]),
                    REQUEST_BLUETOOTH_PERMISSIONS);
        } else {
            startScan();
        }
    }

    // 开始扫描BLE设备
    private void startScan() {
        // 检查蓝牙是否启用
        if (!bluetoothAdapter.isEnabled()) {
            // 启用蓝牙
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, 1);
            return;
        }

        // 获取蓝牙LE扫描器
        bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
        if (bluetoothLeScanner == null) {
            // 获取蓝牙LE扫描器失败
            Toast.makeText(this, "无法获取BLE扫描器", Toast.LENGTH_SHORT).show();
            return;
        }

        // 配置扫描过滤器，只扫描包含我们自定义服务的设备
        List<ScanFilter> filters = new ArrayList<>();
        ScanFilter filter = new ScanFilter.Builder()
                // 设置服务UUID，只获取包含自定义服务的设备，否则将不返回，进行筛选
//                .setServiceUuid(new android.os.ParcelUuid(CUSTOM_SERVICE_UUID))
                .build();
        filters.add(filter);

        // 配置扫描设置
        ScanSettings settings = new ScanSettings.Builder()
                // 设置扫描模式为低延迟 SCAN_MODE_LOW_LATENCY 低延迟、SCAN_MODE_BALANCED 平衡模式、SCAN_MODE_LOW_POWER 低功耗、SCAN_MODE_OPPORTUNISTICSCAN_MODE_OPPORTUNISTIC 不主动扫描，只使用其他app的扫描结果
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                .build();

        // 开始扫描
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        bluetoothLeScanner.startScan(filters, settings, scanCallback);
        isScanning = true;
        scanButton.setText("停止扫描");
        deviceInfoTextView.setText("正在扫描设备...");

        // 定时停止扫描，扫描结束后自动停止
        handler.postDelayed(this::stopScan, SCAN_PERIOD);
    }

    // 停止扫描
    private void stopScan() {
        if (isScanning && bluetoothLeScanner != null) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            bluetoothLeScanner.stopScan(scanCallback);
            isScanning = false;
            scanButton.setText("开始扫描");
            deviceInfoTextView.append("\n扫描已停止");
        }
    }

    // BLE扫描回调
    private final ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            processScanResult(result);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            for (ScanResult result : results) {
                processScanResult(result);
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.e(TAG, "扫描失败，错误码: " + errorCode);
            runOnUiThread(() -> deviceInfoTextView.setText("扫描失败，错误码: " + errorCode));
        }
    };

    // 在类中添加计算距离的方法
    private double calculateDistance(int rssi, int txPower) {
        /*
         * RSSI = TxPower - 10 * n * lg(d)
         * n = 2 (in free space, but in reality it ranges from 2 to 4 depending on environment)
         * d = 10 ^ ((TxPower - RSSI) / (10 * n))
         */

        if (rssi == 0) {
            return -1.0; // 无法确定距离
        }

        double ratio = rssi * 1.0 / txPower;
        if (ratio < 1.0) {
            return Math.pow(10, ratio);
        } else {
            double distance = 0.89976 * Math.pow(ratio, 7.7095) + 0.111;
            return distance;
        }
    }

    // 处理扫描结果，解析广播数据
    private void processScanResult(ScanResult result) {
        if (result == null) return;

        // 获取设备信息，进行权限检查
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        String deviceName = result.getDevice().getName();
        String deviceAddress = result.getDevice().getAddress();
        int rssi = result.getRssi();

        // 获取广播数据
        ScanRecord scanRecord = result.getScanRecord();
        if (scanRecord != null) {
            int txPower = -59 * 6;
            // 解析自定义广播数据
            Map<ParcelUuid, byte[]> customData = parseCustomData(scanRecord);

            // 在UI上显示结果
            runOnUiThread(() -> {
                double distance = calculateDistance(rssi, txPower);

                String distanceStr = distance >= 0 ? String.format("%.2f 米", distance) : "未知距离";
                // 检查是否已经存在该设备的信息，避免重复显示
                String deviceInfo = String.format("设备名称: %s\nMAC地址: %s\n信号强度: %d dBm\n距离估算: %s\n自定义数据: %s",
                        deviceName != null ? deviceName : "未知",
                        deviceAddress,
                        rssi,
                        distanceStr,
                        customData != null ? bytesToHex(customData) : "无");

                String fullInfo = info.toString();
                if (!fullInfo.contains("MAC地址: " + deviceAddress)) {
                    // 如果info中不包含该设备，则添加新设备信息
                    if (info.length() > 0) {
                        info.append("\n\n\n");
                    }
                    info.append(deviceInfo);
                } else {
                    // 如果info中已包含该设备，则更新该设备的信息
                    String devicePattern = "MAC地址: " + deviceAddress;
                    int startIndex = fullInfo.indexOf(devicePattern);
                    if (startIndex > 0) {
                        // 找到该设备信息的起始位置
                        int endIndex = fullInfo.indexOf("\n\n\n", startIndex);
                        if (endIndex == -1) {
                            endIndex = fullInfo.length();
                        }
                        // 替换旧的设备信息
                        String oldDeviceInfo = fullInfo.substring(
                                fullInfo.lastIndexOf("\n\n\n", startIndex) + 3, endIndex);
                        fullInfo = fullInfo.replace(oldDeviceInfo, deviceInfo);
                        info = new StringBuilder(fullInfo);
                    }
                }

                deviceInfoTextView.setText(info.toString());
                Log.d(TAG, "发现设备: " + deviceInfo);
            });
        }
    }

    // 解析广播数据中的自定义信息
    private Map<ParcelUuid, byte[]> parseCustomData(ScanRecord scanRecord) {
        // 这里需要根据服务端定义的广播数据格式进行解析
        // 通常自定义数据会放在Manufacturer Specific Data中
        // 或者Service Data中

        // 示例：获取Manufacturer Specific Data
        // Map<Integer, byte[]> manufacturerData = scanRecord.getManufacturerSpecificData();

        // 示例：获取Service Data
//        byte[] serviceData = scanRecord.getServiceData(new android.os.ParcelUuid(CUSTOM_SERVICE_UUID));
        Map<ParcelUuid, byte[]> serviceData = scanRecord.getServiceData();

        return serviceData;
    }

    // 字节数组转十六进制字符串
    private String bytesToHex(Map<ParcelUuid, byte[]> serviceData) {
        if (serviceData == null || serviceData.isEmpty()) return "";

        StringBuilder sb = new StringBuilder();
        for (Map.Entry<ParcelUuid, byte[]> entry : serviceData.entrySet()) {
            ParcelUuid uuid = entry.getKey();
            byte[] data = entry.getValue();

            sb.append("UUID: ").append(uuid.toString()).append(" -> ");
            for (byte b : data) {
                sb.append(String.format("%02X ", b));
            }
            sb.append("\n");
        }
        return sb.toString().trim();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_BLUETOOTH_PERMISSIONS) {
            boolean allGranted = true;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }
            if (allGranted) {
                startScan();
            } else {
                Toast.makeText(this, "需要权限才能扫描BLE设备", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopScan();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }
}